import { SmoothMap } from "./plugins/smoothMap/smoothMap";
import { clearRoom } from "./plugins/clearRoom/clearRoom";
import { linkRoom } from "./plugins/linkRoom/linkRoom";
import { Coord } from "./utils/Coord";
import { Room } from "./utils/Room";
import Matrix from "../Matrix/Matrix";
import { random } from "game-random/src/random";
import { TILE } from "./enum";
import { DrawLine } from "./utils/DrawLine";
import { MAP, InputTemplate, LoopFunc } from "./Types";

export * from "./plugins";

// 本程序借鉴了 油管上的视频教程，作者 Sebastian Lague
// 链接：https://www.youtube.com/playlist?list=PLFt_AvWsXl0eZgMK_DT5_biRkWXftAOf9
// 制作时查看了 口袋村的大猫 的教程 https://www.jianshu.com/p/449dda187595
// 江夏尧：这个程序的思想很棒，所以我直接抽象出了可以复用的工具类进行地图生成
export class MapGenerator {
    seed: string = "";
    map: MAP;
    width: number;
    height: number;
    smoothRate: number;
    density: number;
    smoothTime: number;
    minRoomSize: number;
    roomTiles: Coord[][] = [];
    rooms: Room[] = [];
    ConnectRoom: typeof DrawLine;
    constructor({
        width,
        height,
        smoothRate = 4, // 1-8 平滑指数，为周围方格数目的和
        smoothTime = 6, // 平滑迭代次数
        density = 0.4, // 0-1 洞穴密度
        seed = Math.random() + "",
        minRoomSize, // 最小洞穴大小
        /** 可以通过设置连接房间的路径来进行连接 */
        ConnectRoom = DrawLine,
    }: InputTemplate) {
        this.minRoomSize = Math.ceil(minRoomSize ?? width / 10);
        this.seed = seed;
        this.width = width;
        this.height = height;
        this.smoothRate = smoothRate;
        this.smoothTime = smoothTime;
        this.density = density;
        this.ConnectRoom = ConnectRoom;
        this.map = this.RandomFillMap(height, width);
    }
    /** 生成随机填充地图 */
    RandomFillMap(height: number, width: number) {
        return new Matrix({
            height,
            width,
            voidValue: 0,
            creator: (x, y) => {
                const seed_ = x + this.seed + y;
                const rand = random(0, 1, true, seed_);
                return rand > this.density ? TILE.Wall : TILE.Void;
            },
        });
    }

    buildMap() {
        console.log("地图使用种子:", this.seed);
        let newMap = [
            ...[...Array(this.smoothTime).keys()].map(() => SmoothMap),
            clearRoom,
            linkRoom,
        ].reduce((col: MAP, cur: LoopFunc, index) => {
            const label = "渲染阶段 " + index;
            console.time(label);
            const result = cur ? cur.call(this, col, this) : col;
            console.timeEnd(label);
            return result;
        }, this.map);
        // 清除中间变量
        this.map = newMap;
        return this;
    }
    /** 渲染函数，可以使用相关渲染插件 */
    render(...Plugins: LoopFunc[]) {
        [...Plugins].reduce((col: MAP, cur: LoopFunc, index) => {
            const label = "渲染阶段 " + index;
            console.time(label);
            const result = cur ? cur.call(this, col, this) : col;
            console.timeEnd(label);
            return result;
        }, this.map);
        this.afterRenderFuncs.forEach((i) => i.call(this));
        return this;
    }
    private afterRenderFuncs: Function[] = [];
    /** 在 render 函数中可以使用 afterRender 来推迟执行渲染函数 */
    afterRender(Func: Function) {
        this.afterRenderFuncs.push(Func);
    }
    get(x: number, y: number) {
        return this.map.get(x, y) || TILE.Wall;
    }
    set(x: number, y: number, value: number) {
        if (y >= 0 && x >= 0 && x < this.map[0].length && y < this.map.length) {
            this.map[y][x] = value;
            return true;
        }
        return false;
    }
}
